<?php

namespace app\admin\controller;

use app\common\controller\Backend;
use app\admin\model\SaleOrder as SaleOrderModel;
use app\admin\model\SaleOrderItem as SaleOrderItemModel;
use app\admin\model\Customer;
use app\admin\model\Manufacturer;
use app\admin\model\Product;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\exception\ValidateException;

/**
 * 销售单管理
 *
 * @icon fa fa-file-text-o
 */
class SaleOrder extends Backend
{
    /**
     * 销售单模型对象
     * @var \app\admin\model\SaleOrder
     */
    protected $model = null;
    
    /**
     * 关联表
     */
    protected $relationSearch = true;
    protected $searchFields = 'manufacturer.name,customer.name';
    
    /**
     * 初始化方法
     */
    public function _initialize()
    {
        parent::_initialize();
        $this->model = new SaleOrderModel();
    }
    
    /**
     * 查看
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            
            // 获取查询参数
            $filter = $this->request->get("filter", '');
            $filter = (array)json_decode($filter, true);
            $op = $this->request->get("op", '', 'trim');
            $op = (array)json_decode($op, true);
            
            // 组装查询条件
            $where = [];
            
            // 客户和厂家搜索
            if (isset($filter['customer_id']) && $filter['customer_id'] !== '') {
                $where['customer_id'] = $filter['customer_id'];
            }
            
            if (isset($filter['manufacturer_id']) && $filter['manufacturer_id'] !== '') {
                $where['manufacturer_id'] = $filter['manufacturer_id'];
            }
            
            // 日期范围搜索
            if (isset($filter['order_date']) && $filter['order_date'] !== '') {
                if (isset($op['order_date']) && $op['order_date'] === 'RANGE') {
                    $range = explode(' - ', $filter['order_date']);
                    if (count($range) == 2) {
                        $where['order_date'] = ['between time', [$range[0] . ' 00:00:00', $range[1] . ' 23:59:59']];
                    }
                }
            }
            
            // 金额范围搜索
            if (isset($filter['total_amount']) && $filter['total_amount'] !== '') {
                if (isset($op['total_amount']) && $op['total_amount'] === 'BETWEEN') {
                    $where['total_amount'] = ['between', explode(',', $filter['total_amount'])];
                } else {
                    $operator = isset($op['total_amount']) ? $op['total_amount'] : '=';
                    $where['total_amount'] = [$operator, $filter['total_amount']];
                }
            }
            
            // 查询数据
            $list = $this->model
                ->with(['customer', 'manufacturer'])
                ->where($where)
                ->order('id', 'desc')
                ->paginate($this->request->request('limit', 10));
            
            $result = ['total' => $list->total(), 'rows' => $list->items()];
            return json($result);
        }
        
        return $this->view->fetch();
    }
    
    /**
     * 添加
     */
    public function add()
    {
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            $items = $this->request->post("items/a");
            
            if (!$params) {
                $this->error(__('Parameter %s can not be empty', ''));
            }
            
            if (!$items || !is_array($items)) {
                $this->error(__('销售单明细不能为空'));
            }
            
            $params = $this->preExcludeFields($params);
            
            if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
                $params[$this->dataLimitField] = $this->auth->id;
            }
            
            // 设置默认下单时间
            if (!isset($params['order_date']) || empty($params['order_date'])) {
                $params['order_date'] = date('Y-m-d H:i:s');
            }
            
            // 计算总重量、总金额、总进货价
            $total_weight = 0;
            $total_purchase_price = 0;
            $total_product_amount = 0;
            
            // 验证销售单明细数据
            foreach ($items as $k => $item) {
                if (empty($item['product_id'])) {
                    $this->error(__('请选择商品'));
                }
                
                if (empty($item['quantity']) || $item['quantity'] <= 0) {
                    $this->error(__('商品数量必须大于0'));
                }
                
                if (empty($item['unit_price']) || $item['unit_price'] <= 0) {
                    $this->error(__('商品单价必须大于0'));
                }
                
                if (empty($item['purchase_price']) || $item['purchase_price'] <= 0) {
                    $this->error(__('进货价必须大于0'));
                }
                
                // 获取产品信息
                $product = Product::get($item['product_id']);
                if (!$product) {
                    $this->error(__('商品不存在'));
                }
                
                // 计算重量 (斤/袋 * 袋/件 * 件数)
                $jin_per_bag = isset($item['jin_per_bag']) ? floatval($item['jin_per_bag']) : floatval($product->jin_per_bag);
                $bags_per_piece = isset($item['bags_per_piece']) ? floatval($item['bags_per_piece']) : floatval($product->bags_per_piece);
                $weight = $jin_per_bag * $bags_per_piece * $item['quantity'];
                $total_weight += $weight;
                
                // 计算进货总价
                $total_purchase_price += floatval($item['purchase_price']) * $item['quantity'];
                
                // 计算商品总价
                $total_product_amount += floatval($item['unit_price']) * $item['quantity'];
            }
            
            // 设置总进货价
            $params['total_purchase_price'] = $total_purchase_price;
            
            // 设置总重量
            $params['total_weight'] = $total_weight;
            
            // 计算总金额 = 商品总价 - 优惠金额
            $discount_amount = isset($params['discount_amount']) ? floatval($params['discount_amount']) : 0;
            $params['total_amount'] = $total_product_amount - $discount_amount;
            
            $result = false;
            Db::startTrans();
            try {
                // 验证
                $validate = validate('SaleOrder');
                $validate->scene('add')->check($params);
                
                // 保存主表数据
                $result = $this->model->allowField(true)->save($params);
                $sale_order_id = $this->model->id;
                
                // 保存明细数据
                foreach ($items as $item) {
                    // 获取产品信息用于存储快照
                    $product = Product::get($item['product_id']);
                    
                    $itemData = [
                        'sale_order_id' => $sale_order_id,
                        'product_id' => $item['product_id'],
                        'quantity' => $item['quantity'],
                        'purchase_price' => $item['purchase_price'],
                        'unit_price' => $item['unit_price'],
                        'jin_per_bag' => isset($item['jin_per_bag']) ? $item['jin_per_bag'] : $product->jin_per_bag,
                        'bags_per_piece' => isset($item['bags_per_piece']) ? $item['bags_per_piece'] : $product->bags_per_piece,
                    ];
                    
                    $orderItem = new SaleOrderItemModel();
                    $orderItem->allowField(true)->save($itemData);
                }
                
                // 创建账单记录
                $this->createBillRecord($params, $sale_order_id);
                
                Db::commit();
            } catch (ValidateException $e) {
                Db::rollback();
                $this->error($e->getMessage());
            } catch (PDOException $e) {
                Db::rollback();
                $this->error($e->getMessage());
            } catch (Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
            
            if ($result !== false) {
                $this->success();
            } else {
                $this->error(__('No rows were inserted'));
            }
        }
        
        return $this->view->fetch();
    }
    
    /**
     * 编辑
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        
        // 获取关联的销售单明细
        $items = SaleOrderItemModel::where('sale_order_id', $ids)->select();
        $this->view->assign("items", $items);
        
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            $items = $this->request->post("items/a");
            
            if (!$params) {
                $this->error(__('Parameter %s can not be empty', ''));
            }
            
            if (!$items || !is_array($items)) {
                $this->error(__('销售单明细不能为空'));
            }
            
            $params = $this->preExcludeFields($params);
            
            // 计算总重量、总金额、总进货价
            $total_weight = 0;
            $total_purchase_price = 0;
            $total_product_amount = 0;
            
            // 验证销售单明细数据
            foreach ($items as $k => $item) {
                if (empty($item['product_id'])) {
                    $this->error(__('请选择商品'));
                }
                
                if (empty($item['quantity']) || $item['quantity'] <= 0) {
                    $this->error(__('商品数量必须大于0'));
                }
                
                if (empty($item['unit_price']) || $item['unit_price'] <= 0) {
                    $this->error(__('商品单价必须大于0'));
                }
                
                if (empty($item['purchase_price']) || $item['purchase_price'] <= 0) {
                    $this->error(__('进货价必须大于0'));
                }
                
                // 获取产品信息
                $product = Product::get($item['product_id']);
                if (!$product) {
                    $this->error(__('商品不存在'));
                }
                
                // 计算重量 (斤/袋 * 袋/件 * 件数)
                $jin_per_bag = isset($item['jin_per_bag']) ? floatval($item['jin_per_bag']) : floatval($product->jin_per_bag);
                $bags_per_piece = isset($item['bags_per_piece']) ? floatval($item['bags_per_piece']) : floatval($product->bags_per_piece);
                $weight = $jin_per_bag * $bags_per_piece * $item['quantity'];
                $total_weight += $weight;
                
                // 计算进货总价
                $total_purchase_price += floatval($item['purchase_price']) * $item['quantity'];
                
                // 计算商品总价
                $total_product_amount += floatval($item['unit_price']) * $item['quantity'];
            }
            
            // 设置总进货价
            $params['total_purchase_price'] = $total_purchase_price;
            
            // 设置总重量
            $params['total_weight'] = $total_weight;
            
            // 计算总金额 = 商品总价 - 优惠金额
            $discount_amount = isset($params['discount_amount']) ? floatval($params['discount_amount']) : 0;
            $params['total_amount'] = $total_product_amount - $discount_amount;
            
            $result = false;
            Db::startTrans();
            try {
                // 验证
                $validate = validate('SaleOrder');
                $validate->scene('edit')->check($params);
                
                // 更新主表数据
                $result = $row->allowField(true)->save($params);
                
                // 先删除原有明细
                SaleOrderItemModel::where('sale_order_id', $ids)->delete();
                
                // 保存新的明细数据
                foreach ($items as $item) {
                    // 获取产品信息用于存储快照
                    $product = Product::get($item['product_id']);
                    
                    $itemData = [
                        'sale_order_id' => $ids,
                        'product_id' => $item['product_id'],
                        'quantity' => $item['quantity'],
                        'purchase_price' => $item['purchase_price'],
                        'unit_price' => $item['unit_price'],
                        'jin_per_bag' => isset($item['jin_per_bag']) ? $item['jin_per_bag'] : $product->jin_per_bag,
                        'bags_per_piece' => isset($item['bags_per_piece']) ? $item['bags_per_piece'] : $product->bags_per_piece,
                    ];
                    
                    $orderItem = new SaleOrderItemModel();
                    $orderItem->allowField(true)->save($itemData);
                }
                
                // 查找之前的账单记录
                $oldBill = Db::name('bill')->where('related_sale_order_id', $ids)->where('source', 1)->find();
                
                // 如果存在旧账单，则更新，否则创建新账单
                if ($oldBill) {
                    $this->updateBillRecord($params, $ids, $oldBill);
                } else {
                    $this->createBillRecord($params, $ids);
                }
                
                Db::commit();
            } catch (ValidateException $e) {
                Db::rollback();
                $this->error($e->getMessage());
            } catch (PDOException $e) {
                Db::rollback();
                $this->error($e->getMessage());
            } catch (Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
            
            if ($result !== false) {
                $this->success();
            } else {
                $this->error(__('No rows were updated'));
            }
        }
        
        $this->view->assign("row", $row);
        return $this->view->fetch();
    }
    
    /**
     * 删除
     */
    public function del($ids = "")
    {
        if (!$this->request->isPost()) {
            $this->error(__("Invalid parameters"));
        }
        $ids = $ids ? $ids : $this->request->post("ids");
        if (empty($ids)) {
            $this->error(__('Parameter %s can not be empty', 'ids'));
        }
        
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        
        $list = $this->model->where($pk, 'in', $ids)->select();
        
        $count = 0;
        Db::startTrans();
        try {
            foreach ($list as $k => $v) {
                // 删除关联的销售单明细
                SaleOrderItemModel::where('sale_order_id', $v->id)->delete();
                
                // 删除关联的账单记录
                Db::name('bill')->where('related_sale_order_id', $v->id)->where('source', 1)->delete();
                
                $count += $v->delete();
            }
            Db::commit();
        } catch (PDOException $e) {
            Db::rollback();
            $this->error($e->getMessage());
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        
        if ($count) {
            $this->success();
        } else {
            $this->error(__('No rows were deleted'));
        }
    }
    
    /**
     * 创建账单记录
     * @param array $params 销售单参数
     * @param int $sale_order_id 销售单ID
     */
    protected function createBillRecord($params, $sale_order_id)
    {
        // 查询客户和厂家当前余额
        $customer = Customer::get($params['customer_id']);
        $manufacturer = Manufacturer::get($params['manufacturer_id']);
        
        // 查询客户最新的账单记录
        $lastCustomerBill = Db::name('bill')
            ->where('customer_id', $params['customer_id'])
            ->where('bill_type', 2)
            ->order('id', 'desc')
            ->find();
        
        // 查询厂家最新的账单记录
        $lastManufacturerBill = Db::name('bill')
            ->where('manufacturer_id', $params['manufacturer_id'])
            ->where('bill_type', 1)
            ->order('id', 'desc')
            ->find();
        
        // 设置客户起始余额
        $customer_opening_balance = $lastCustomerBill ? $lastCustomerBill['customer_closing_balance'] : 0;
        
        // 设置厂家起始余额
        $manufacturer_opening_balance = $lastManufacturerBill ? $lastManufacturerBill['manufacturer_closing_balance'] : 0;
        
        // 客户当日欠款（总金额）
        $customer_current_debt = $params['total_amount'];
        
        // 客户当日付款
        $customer_current_payment = isset($params['customer_payment']) ? floatval($params['customer_payment']) : 0;
        
        // 客户剩余欠款
        $customer_closing_balance = $customer_opening_balance + $customer_current_debt - $customer_current_payment;
        
        // 当日欠厂家货款（总进货价）
        $manufacturer_current_debt = $params['total_purchase_price'];
        
        // 当日付款给厂家
        $manufacturer_current_payment = isset($params['manufacturer_payment']) ? floatval($params['manufacturer_payment']) : 0;
        
        // 厂家剩余欠款
        $manufacturer_closing_balance = $manufacturer_opening_balance + $manufacturer_current_debt - $manufacturer_current_payment;
        
        // 创建客户账单记录
        $customerBillData = [
            'customer_id' => $params['customer_id'],
            'bill_date' => date('Y-m-d H:i:s'),
            'customer_opening_balance' => $customer_opening_balance,
            'customer_current_debt' => $customer_current_debt,
            'customer_current_payment' => $customer_current_payment,
            'customer_closing_balance' => $customer_closing_balance,
            'notes' => isset($params['notes']) ? $params['notes'] : '销售单生成',
            'source' => 1, // 1下单
            'related_sale_order_id' => $sale_order_id,
            'bill_type' => 2, // 客户账单
        ];
        
        Db::name('bill')->insert($customerBillData);
        
        // 创建厂家账单记录
        $manufacturerBillData = [
            'manufacturer_id' => $params['manufacturer_id'],
            'bill_date' => date('Y-m-d H:i:s'),
            'manufacturer_opening_balance' => $manufacturer_opening_balance,
            'manufacturer_current_debt' => $manufacturer_current_debt,
            'manufacturer_current_payment' => $manufacturer_current_payment,
            'manufacturer_closing_balance' => $manufacturer_closing_balance,
            'notes' => isset($params['notes']) ? $params['notes'] : '销售单生成',
            'source' => 1, // 1下单
            'related_sale_order_id' => $sale_order_id,
            'bill_type' => 1, // 厂家账单
        ];
        
        Db::name('bill')->insert($manufacturerBillData);
    }
    
    /**
     * 更新账单记录
     * @param array $params 销售单参数
     * @param int $sale_order_id 销售单ID
     * @param array $oldBill 旧账单记录
     */
    protected function updateBillRecord($params, $sale_order_id, $oldBill)
    {
        // 先删除旧的账单记录
        Db::name('bill')->where('related_sale_order_id', $sale_order_id)->where('source', 1)->delete();
        
        // 创建新的账单记录
        $this->createBillRecord($params, $sale_order_id);
    }
} 